package com.suray.wcs.service.core.path.api;

import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.path.enums.Direction;
import com.suray.basic.wcs.path.enums.NodeType;
import com.suray.basic.wcs.utils.ParamConfig;
import com.suray.wcs.service.pojo.Rgv;
import com.suray.wcs.service.system.entity.RgvDB;
import com.suray.wcs.service.util.WcsUtil;

import java.util.List;

/**
 * 给路径节点设置行驶速度
 */
public class GeneralPathNodeSpeed {

    private Rgv rgv;
    private List<Node> nodeList;

    public GeneralPathNodeSpeed(Rgv rgv, List<Node> nodeList) {
        this.rgv = rgv;
        this.nodeList = nodeList;
    }

    public void generalSpeed() {
        analyzeNodesSpeed(rgv, nodeList);
    }

    /**
     * 解析路径速度
     * @param rgv
     * @param nodeList
     */
    private void analyzeNodesSpeed(Rgv rgv, List<Node> nodeList) {
        RgvDB rgvDB = rgv.getRgvDB();
        for (int i = 0; i < nodeList.size(); i++) {
            Node node = nodeList.get(i);
            switch (node.getNodeType()) {
                case C:
                    i = analyzeNodesSpeed(i, nodeList, ParamConfig.specialSpeedDistance, rgvDB.getChargeSpeed());
                    break;
                case CONNECTION:
                    i = analyzeNodesSpeed(i, nodeList, ParamConfig.specialSpeedDistance, rgvDB.getConnectNodeSpeed());
                    break;
                case L:
                    i = analyzeNodesSpeed(i, nodeList, ParamConfig.specialSpeedDistance, rgvDB.getLiftSpeed());
                    break;
                case AD:
                    i = analyzeNodesSpeed(i, nodeList, ParamConfig.specialSpeedDistance, rgvDB.getDoorSpeed());
                    break;
                default:
                    node.setSpeed(rgvDB.getSpeed());
                    break;
            }
        }
    }

    /**
     * 设置节点速度
     * @param index
     * @param nodeList
     * @param specialSpeedDistance
     * @param speed
     * @return 路径下标
     */
    private int analyzeNodesSpeed(int index, List<Node> nodeList, int specialSpeedDistance, Integer speed) {
        //进入
        nodeList.get(index).setSpeed(speed);
        Direction dir = null;
        int dis = 0;
        int nodeIndex = index - 1;
        while (dis < specialSpeedDistance) {
            if (nodeIndex < 0) {
                break;
            }

            Node node = nodeList.get(nodeIndex--);
            if (isSpecialNode(node)) {
                break;
            }

            Direction tempDir = WcsUtil.analyzeDir(node, nodeList.get(nodeIndex + 2));
            if (dir == null) {
                dir = tempDir;
            } else if (dir != tempDir) {
                break;
            }

            dis += setNodeSpeed(node, speed, dir);
        }

        //离开
        dis = 0;
        nodeIndex = index + 1;
        while (dis < specialSpeedDistance) {
            if (nodeIndex >= nodeList.size()) {
                break;
            }

            Node node = nodeList.get(nodeIndex);
            if (isSpecialNode(node)) {
                break;
            }

            Direction tempDir = WcsUtil.analyzeDir(nodeList.get(nodeIndex - 1), node);
            if (dir == null) {
                dir = tempDir;
            } else if (dir != tempDir) {
                break;
            }

            dis += setNodeSpeed(node, speed, dir);

            nodeIndex++;
        }

        return nodeIndex - 1;
    }

    private boolean isSpecialNode(Node node) {
        if (node.getNodeType() == NodeType.C
                || node.getNodeType() == NodeType.AD
                || node.getNodeType() == NodeType.L
                || node.getNodeType() == NodeType.CONNECTION
        ) {
            return true;
        }

        return false;
    }

    /**
     *
     * @param node
     * @param speed
     */
    private int setNodeSpeed(Node node, int speed, Direction dir) {
        int dis;

        switch (dir) {
            case UP:
            case DOWN:
                dis = node.getOffsetX();
                break;
            case LEFT:
            case RIGHT:
                dis = node.getOffsetY();
                break;
            default:
                throw new RuntimeException("路径方向错误");
        }

        node.setSpeed(speed);

        return dis;
    }
}
